﻿//=====================================================================================================
// LocalizationLibrary
// The Localization Library is a collection of reusable software components that provide 
// support for localization. This library enables you to localize WPF, Silverlight and WP7 applications.
// (http://localizationlibrary.codeplex.com)
//=====================================================================================================
// Author: Nicola Gallo (Website: www.nicola.gallo.name, Email: nicolagmt@hotmail.it) 
//=====================================================================================================
using ReflectionStudio.Core.Reflection;
namespace ReflectionStudio.LocalizationLibrary
{
    //.NET References
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text;

    //LocalizationLibrary References
    
    /// <summary>
    /// Defines localization models' table.
    /// </summary>
    internal class LocalizationModelsTable
    {
        //Fields

        /// <summary>
        /// Gets registered LocalizationModels.
        /// </summary>
        protected readonly Dictionary<int, LocalizationModelRef> RegisteredLocalizationModel;

        //Constructos

        /// <summary>
        /// Default constructor.
        /// </summary>
        internal LocalizationModelsTable()
        {
            this.RegisteredLocalizationModel = new Dictionary<int, LocalizationModelRef>();
        }

        //Methods

        /// <summary>
        /// Check whether the input <paramref name="localizationModelRef"/> is alive. If it's not alive remove it 
        /// from the <see cref="LocalizationModelsTable.RegisteredLocalizationModel"/>.
        /// </summary>
        /// <param name="localizationModelRef"></param>
        /// <returns>True the input <paramref name="localizationModelRef"/> is alive, False otherwise.</returns>
        private bool CheckItem(LocalizationModelRef localizationModelRef)
        {
            bool retVal = true;
            if (localizationModelRef == null)
            {
                retVal = false;
            }
            else if (!localizationModelRef.IsAlive) 
            {
                lock (this.RegisteredLocalizationModel)
                {
                    this.RegisteredLocalizationModel.Remove(localizationModelRef.GetHashCode());
                }
                retVal = false;
            }
            return retVal;
        }

        /// <summary>
        /// Publishes all the new value of properties.
        /// </summary>
        /// <returns>Returns a <see cref="PropertyInfo"/> array whom contains all the properties published.</returns>
        public PropertyInfoRef[] PublishAllPropertiesValue()
        {
            return this.PublishAllPropertiesValue(null);
        }

        /// <summary>
        /// Publishes all the new value of properties.
        /// </summary>
        /// <param name="localizationModels">if equals to null then publish all localization model, otherwise only those in the list.</param>
        /// <returns>Returns a <see cref="PropertyInfo"/> array whom contains all the properties published.</returns>
        public PropertyInfoRef[] PublishAllPropertiesValue(List<Object> localizationModels)
        {
            List<PropertyInfoRef> retVal = new List<PropertyInfoRef>();
            lock (this.RegisteredLocalizationModel)
            {
                LocalizationModelRef[] localizationModelRefs = this.RegisteredLocalizationModel.Values.ToArray();
                foreach (var localizationModelRef in localizationModelRefs)
                {
                    if (this.CheckItem(localizationModelRef))
                    {
                        if ((localizationModels != null) && (!localizationModels.Contains(localizationModelRef.Target)))
                        {
                            continue;
                        }
                        PropertyInfoRef[] propertyInfoRefs = localizationModelRef.PublishAllPropertiesValue();
                        foreach (var propertyInfoRef in propertyInfoRefs)
                        {
                            retVal.Add(propertyInfoRef);
                        }
                    }
                }
            }
            return retVal.ToArray();
        }

        /// <summary>
        /// Adds the input <paramref name="localizationModelRef"/> at the list of localization model registered.
        /// </summary>
        /// <param name="localizationModelRef"></param>
        /// <returns>True if the input <paramref name="localizationModelRef"/> is registered, False otherwise.</returns>
        public bool AddLocalizationModelRef(LocalizationModelRef localizationModelRef)
        {
            bool retVal = false;
            lock (this.RegisteredLocalizationModel)
            {
                if (!this.RegisteredLocalizationModel.ContainsKey(localizationModelRef.GetHashCode()))
                {
                    this.RegisteredLocalizationModel.Add(localizationModelRef.GetHashCode(), localizationModelRef);
                    retVal = true;
                }
            }
            return retVal;
        }

        /// <summary>
        /// Resets the <see cref="LocalizationModelsTable"/>.
        /// </summary>
        public void Reset() 
        {
            lock (this.RegisteredLocalizationModel)
            {
                this.RegisteredLocalizationModel.Clear();
            }
        }
    }
}